package org.dromara.web.plugins.telegram;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.pengrad.telegrambot.TelegramBot;
import com.pengrad.telegrambot.UpdatesListener;
import com.pengrad.telegrambot.model.Update;
import com.pengrad.telegrambot.model.request.Keyboard;
import com.pengrad.telegrambot.model.request.ReplyKeyboardMarkup;
import com.pengrad.telegrambot.model.request.ReplyParameters;
import com.pengrad.telegrambot.request.SendMessage;
import com.pengrad.telegrambot.response.SendResponse;
import io.lettuce.core.RedisClient;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.pubsub.StatefulRedisPubSubConnection;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.redis.utils.CacheUtils;
import org.dromara.dao.business.domain.Model;
import org.dromara.dao.business.domain.User;
import org.dromara.dao.business.mapper.ModelMapper;
import org.dromara.web.plugins.provider.ModelProviderFactory;
import org.dromara.web.service.business.UserService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import software.amazon.awssdk.core.pagination.sync.PaginatedResponsesIterator;

import java.util.List;


@Slf4j
//@Component
public class TelegramBotPlugins implements InitializingBean {


    TelegramBot bot;

    private static final String TELEGRAM_BOT_TOKEN = "7723951953:AAEQfKB6-8xFNhWvjzQIMe7cN9ZFjxBAEro";

    private static final String WELCOME_MESSAGE = "欢迎使用MieraChatBot, 请在菜单栏中选择需要的操作";
    private static final String ERROR_MESSAGE = "系统异常，请联系管理员";
    private static final String MODEL_SELECT_SUCCESS = "模型选择成功, 请输入/chat {您的问题}来与模型对话";
    private static final String USER_BALANCE_RECHARGE = "您的账户余额不足，请先充值积分再使用";
    private static final String COMMAND_SELECT_MODEL = "选择对话模型";
    private static final String COMMAND_RECHARGE_L_GRADE = "充值普通积分";
    private static final String COMMAND_RECHARGE_H_GRADE = "充值高级积分";
    private static final String MODEL_SELECT_REPLY_TITLE = "请选择对话模型";
    private static final String USER_NAME_FORMAT = "telegram-u-%s";
    private static final String RECHARGE_MESSAGE_HIGH = "请往以下USDT-ERC20地址充值: %s (1U=1高级积分)";
    private static final String RECHARGE_MESSAGE_LOW = "请往以下USDT-ERC20地址充值: %s (1U=1普通积分)";


    @Autowired
    ThreadPoolTaskExecutor  threadPoolTaskExecutor;
    @Autowired
    UserService userService;
    @Autowired
    ModelMapper modelMapper;
    @Autowired
    RedisTemplate<String,String> redisTemplate;
    @Autowired
    ModelProviderFactory modelProviderFactory;

    @Override
    public void afterPropertiesSet() throws Exception {
        bot = new TelegramBot(TELEGRAM_BOT_TOKEN);


        bot.setUpdatesListener(updates -> {
            // ... process updates
            threadPoolTaskExecutor.execute(() -> {
                updates.stream().forEach(update -> {
                    dealUpdate(update);
                });
            });
            // return id of last processed update or confirm them all
            return UpdatesListener.CONFIRMED_UPDATES_ALL;
// Create Exception Handler
        }, e -> {
            if (e.response() != null) {
                // got bad response from telegram
                e.response().errorCode();
                e.response().description();
            } else {
                // probably network error
                e.printStackTrace();
            }
        });
    }



    private void dealUpdate(final Update update) {
        log.info("update:{}", update);
        Long chatId = update.message().chat().id();
        Integer messageId = update.message().messageId();
        String text = update.message().text();
        Long fromUserId = update.message().from().id();
        // 检查是否注册
        threadPoolTaskExecutor.execute(()->{
            userService.telegramUserRegister(username(update.message().from().id()));
        });

        try {
            if (update.message().newChatMembers() != null && update.message().newChatMembers().length > 0) {
                for (int i = 0; i < update.message().newChatMembers().length; i++) {
                    // 注册新用户
                    userService.telegramUserRegister(username(update.message().newChatMembers()[i].id()));
                }
            }

            if (COMMAND_RECHARGE_L_GRADE.equals(text)) {
                // 充值低级积分
                String address = userService.telegramUserLowAddress(username(update.message().from().id()));
                showWelcomeBotCommand(String.format(RECHARGE_MESSAGE_LOW, address), chatId, messageId);
                return;
            } else if (COMMAND_RECHARGE_H_GRADE.equals(text)) {
                // 充值高级积分
                String address = userService.telegramUserHighAddress(username(update.message().from().id()));
                showWelcomeBotCommand(String.format(RECHARGE_MESSAGE_HIGH, address), chatId, messageId);
                return;
            } else if (COMMAND_SELECT_MODEL.equals(text)) {
                // 选择模型
                showModelSelectCommand(chatId, messageId);
                return;
            }

            if (StringUtils.isNotEmpty(update.message().text()) && update.message().text().startsWith("/chat")) {
                String question = update.message().text().replaceFirst("/chat ", "");
                Model model = getUserModel(username(fromUserId));
                if (model == null) {
                    showModelSelectCommand(chatId, messageId);
                    return;
                }

                try{
                    User user = userService.telegramUserInfo(username(fromUserId));
                    userService.userBalanceChange(user.getId(), - model.getDiamondFee(), - model.getStarFee(), "模型调用");
                }catch (Exception e) {
                    showWelcomeBotCommand(USER_BALANCE_RECHARGE, chatId, messageId);
                    return;
                }

                String aiResponse = modelProviderFactory.chatResponse(model, question);
                String response = model.getName() + ": " + aiResponse; ;
                showWelcomeBotCommand(response, chatId, messageId);
                return;
            }

            if (update.message().replyToMessage() != null) {
                if (update.message().replyToMessage().text() != null && update.message().replyToMessage().text().equals(MODEL_SELECT_REPLY_TITLE)) {
                    // 回复了模型选择

                    if (StringUtils.isNotEmpty(update.message().text())) {
                        String content = update.message().text();
                        String modelName = update.message().text().substring(0, content.indexOf("("));
                        Model model = modelMapper.selectOne(new LambdaQueryWrapper<Model>().eq(Model::getName, modelName).eq(Model::getStatus, true));
                        if (model != null) {
                            cacheUserModel(username(fromUserId), model);
                            showWelcomeBotCommand(MODEL_SELECT_SUCCESS, chatId, messageId);
                            return;
                        }
                    }

                }
            }

        }catch (Exception e) {
            showWelcomeBotCommand(ERROR_MESSAGE, chatId, messageId);
            return;
        }

        showWelcomeBotCommand(WELCOME_MESSAGE, chatId, null);

    }


    private void showModelSelectCommand(Long chatId, Integer messageId) {

        List<Model> models = modelMapper.selectList(new LambdaQueryWrapper<Model>().eq(Model::getStatus, true));
        String[][] commands = new String[models.size()][];
        for (int i = 0; i < models.size(); i++) {
            Model model = models.get(i);
            if (model.getStarFee() != null && model.getStarFee() > 0) {
                commands[i] = new String[]{String.format("%s(%s高级积分)", model.getName(), model.getStarFee())};
            } else {
                commands[i] = new String[]{String.format("%s(%s普通积分)", model.getName(), model.getDiamondFee())};
            }

        }

        Keyboard replyKeyboardMarkup = new ReplyKeyboardMarkup(commands)
            .oneTimeKeyboard(false)   // optional
            .resizeKeyboard(true)    // optional
            .selective(false);        // optional
        SendMessage sendMessage = new SendMessage(chatId, MODEL_SELECT_REPLY_TITLE)
            .replyMarkup(replyKeyboardMarkup)
            .replyParameters(new ReplyParameters(messageId));
        SendResponse response = bot.execute(sendMessage);
    }


    private void showWelcomeBotCommand(String text, Long chatId, Integer messageId) {
        Keyboard replyKeyboardMarkup = new ReplyKeyboardMarkup(
            new String[]{COMMAND_SELECT_MODEL},
            new String[]{COMMAND_RECHARGE_L_GRADE, COMMAND_RECHARGE_H_GRADE})
            .oneTimeKeyboard(false)   // optional
            .resizeKeyboard(true)    // optional
            .selective(false);        // optional
        SendMessage sendMessage = new SendMessage(chatId, text)
            .replyMarkup(replyKeyboardMarkup)
            .replyParameters(new ReplyParameters(messageId));
        SendResponse response = bot.execute(sendMessage);
    }

    private String username(Long userId) {
        return String.format(USER_NAME_FORMAT, userId.toString());
    }


    private void cacheUserModel(String username, Model model) {
        redisTemplate.opsForValue().set("TELEGRAM_USER_MODEL_SELECTION:" + username, JSON.toJSONString(model));

    }

    private Model getUserModel(String username) {
        String ret = redisTemplate.opsForValue().get("TELEGRAM_USER_MODEL_SELECTION:" + username);
        return StringUtils.isEmpty(ret) ? null : JSON.parseObject(ret, Model.class);
    }
}
